#-------------------------------------------------------------------------------
# Name:        CropDetcShortCircuit
# Purpose:
#
# Author:      Daiyusi
#
# Created:     23/07/2021
# Copyright:   (c) asus 2021
# Licence:     <your licence>
#-------------------------------------------------------------------------------

import numpy as np
import os
from PIL import Image,ImageFont,ImageDraw
import matplotlib.pyplot as plt

class CropDetc2:
    def avg_sum(self, im):
        # 面均值
        s = np.float(0)
        h, w = im.shape
        for i in range(h):
            for j in range(w):
                s = s * ((i * w + j) / (i * w + j + 1)) + im[i, j] / (i * w + j + 1)
        return s

    def max_avg_sum(self, im):
        # 线均值最大值
        h, w = im.shape
        maxs = 0
        for i in range(w):
            s = np.float(0)
            for j in range(h):
                s = s * (j / (j + 1)) + im[j, i] / (j + 1)
            if s > maxs:
                maxs = s
        return maxs

    def max2_avg_sum(self, im):
        # 半线均值最大值
        h, w = im.shape
        h2 = int(h / 2)
        maxs1 = self.max_avg_sum(im[0:h2, 0:])
        maxs2 = self.max_avg_sum(im[h2:, 0:])

        if maxs1 > maxs2:
            return maxs1
        else:
            return maxs2
        '''
        s = (maxs1+maxs2)/2
        return s
        '''

    def max3_avg_sum(self, im):
        # (半)线均值最大值与面均值的加权平均
        s = np.float(0)
        s0 = self.avg_sum(im)
        s1 = self.max_avg_sum(im)
        s2 = self.max2_avg_sum(im)
        s = 0.7 * s2 + 0.3 * s0
        return s

    def uncovSearch(self, avgT, meanT):
        # 头尾板搜索计数,以p倍meanT为界
        n = [0, 0]  # [头,尾]
        p = 1.25

        for i in avgT:
            if i > p * meanT:
                n[0] = n[0] + 1
            else:
                break

        for i in avgT[::-1]:
            if i > p * meanT:
                n[1] = n[1] + 1
            else:
                break

        print('n:', n)
        return n

    def T2P(self, T, minT, maxT):
        # P = (T-minT)*255/(maxT-minT)
        k = 255 / (maxT - minT)
        P = []


        if type(T) is list:
            for i in T:
                p0 = (i - minT) * k
                P.append(p0)
        else:
            P = (T - minT) * k

        return P

    def stdDetect(self, im, minT, maxT, num):
        # 单槽板极短路检测
        levelSC = [0, 1, 2, 3]
        diag = [0 for i in range(num)]
        avgT = [0 for i in range(num)]
        h, w = im.shape
        stp = w / num

        # 极板特征值列表求取
        for i in range(num):
            p1 = int(i * stp)
            p2 = int((i + 1) * stp)
            subim = im[0:, p1:p2]
            avgT[i] = self.max3_avg_sum(subim)
            # print('avgT[', str(i + 1), ']:', avgT[i])

        meanT = np.mean(avgT)  # 均值
        stdT = np.std(avgT)  # 标准差
        #    print('meanT1:',meanT)

        difT = avgT - meanT
        uncov = [1 for i in range(num)]  # 有多层盖布处标记0
        num_uncov = num
        sum_uncov = 0
        for i in range(num):
            if difT[i] < -20:
                num_uncov = num_uncov - 1
                uncov[i] = 0
            sum_uncov = sum_uncov + uncov[i] * avgT[i]

        meanT = sum_uncov / num_uncov
        # print('meanT:', meanT)

        # 前后端n个板极忽略，不纳入均值计算

        T1 = 45  # 盖布与不盖布的均温划分界限
        n = [0, 0]
        # x = self.T2P(T1, minT, maxT)
        # print(x)
        if meanT < 155:
            n = self.uncovSearch(avgT, meanT)
            for i in range(-n[1], n[0]):
                if uncov[i] == 1:
                    # uncov[i] = 0
                    num_uncov = num_uncov - 1
                    sum_uncov = sum_uncov - avgT[i]
            meanT = sum_uncov / num_uncov

        difT = avgT - meanT

        # 忽略前后n个板极，以及多层盖布后求标准差
        avgT_normal = []
        for i in range(n[0], num - n[1]):
            if uncov[i] == 1:
                avgT_normal.append(avgT[i])
        stdT = np.std(avgT_normal)

        # print('meanT2:', meanT)
        # print('stdT:', stdT)
        # print('avgT:', avgT)
        # print('difT:', difT)

        k3, k2, k1 = [4, 2, 1.7]

        # 标准差过小
        thrSTD = 0.1
        if stdT < thrSTD * meanT:
            k3, k2, k1 = [5, 3, 2]

        for i in range(n[0], num - n[1]):
            if uncov[i] == 1:
                if difT[i] > k3 * stdT:
                    diag[i] = levelSC[3]
                elif difT[i] > k2 * stdT:
                    diag[i] = levelSC[2]
                elif difT[i] > k1 * stdT:
                    diag[i] = levelSC[1]

        # 对最前、后n块板极中未被多层盖布遮挡的板极单独做阈值检测
        thT = [90, 95, 105]
        th = self.T2P(thT, minT, maxT)

        print('th: ', th)
        # th = [135,145,160] # 两端板极检测阈值
        for i in range(-n[1], n[0]):
            if uncov[i] == 1:
                if avgT[i] > th[2]:
                    diag[i] = levelSC[3]
                elif avgT[i] > th[1]:
                    diag[i] = levelSC[2]
                elif avgT[i] > th[0]:
                    diag[i] = levelSC[1]

        return diag

    def DistorRemove(self, im, k1, k2):
        # 桶形畸变矫正
        s = im.shape
        img = np.zeros(s)
        img = np.uint8(img)

        for l1 in range(s[0]):
            y = l1 - s[0] / 2

            for l2 in range(s[1]):
                x = l2 - s[1] / 2
                x1 = np.round(x * (1 + k1 * x * x + k2 * y * y))
                y1 = np.round(y * (1 + k1 * x * x + k2 * y * y))
                x1 = np.int(x1 + s[1] / 2)
                y1 = np.int(y1 + s[0] / 2)

                # 超出边界部分强制为0
                if x1 < 0 and x1 >= s[1] and y1 < 0 and y1 >= s[0]:
                    img[l1, l2] = 0;
                else:
                    img[l1, l2] = im[y1, x1]
        return img

    def CropOfBars(im):
        # 单槽自动裁剪（待完善）
        pass

    def DecInit(self, num1, num2, num3):
        # 生成key为‘槽号-板极号’，值为0的初始化字典
        diag = {}
        for i in range(num1[0], num1[1] + 1):
            for j in range(num2[0], num2[1] + 1):
                key = str(i) + '-' + str(j)
                diag[key] = [0 for i in range(num3)];
        return diag

    def ShortCircuitDetect(self, im, minT=30, maxT=90, num3=38, num2=[1, 12], num1=[1, 2]):
        # 短路检测主程序
        im = im.convert('L')  # 转灰度图
        im = np.array(im)  # 图片转数组形式存储

        # 生成初始化字典,全0
        diag = self.DecInit(num1, num2, num3)

        # 桶形畸变矫正
        k1 = -3e-7;
        k2 = -4e-7;
        img = self.DistorRemove(im, k1, k2)
        # plt.imshow(img, cmap='gray', interpolation='bicubic')
        # plt.show()

        # 手动定位裁剪
        p = [513, 942, 4, 465]  # 整槽1、2的上下纵坐标位置
        # q = [[[21,14,95,370],[116,19,194,380],[214,20,300,389],[321,27,413,398],[429,27,519,409],[548,24,637,406],[668,34,755,418],[779,35,864,411],[899,30,967,405],[1010,32,1069,412],[1106,35,1170,406],[1205,32,1264,400]],[[13,32,114,416],[117,35,205,415],[223,26,310,416],[331,25,422,418],[447,24,543,419],[559,25,657,424],[679,26,777,425],[796,29,884,426],[905,36,1000,433],[1014,42,1099,436],[1120,53,1199,439],[1229,56,1277,444]],]
        q = [[[10, 13, 101, 370], [116, 16, 192, 377], [216, 18, 295, 388], [321, 22, 414, 395], [430, 24, 522, 404],
              [550, 27, 641, 408], [664, 30, 754, 411], [784, 32, 853, 410], [902, 34, 970, 413], [1010, 35, 1070, 405],
              [1109, 43, 1172, 402], [1202, 37, 1267, 402]],
             [[3, 33, 113, 418], [119, 28, 213, 416], [226, 29, 311, 416], [332, 26, 423, 418], [447, 24, 542, 419],
              [561, 26, 661, 422], [676, 27, 775, 425], [802, 34, 886, 428], [908, 39, 998, 431], [1017, 47, 1098, 435],
              [1123, 56, 1197, 440], [1229, 56, 1279, 444]]]
        # 所有单槽中的板极短路检测
        for i in range(num1[1] - num1[0] + 1):
            # 上、下整槽分离
            imBars = img[(p[2 * i] - 1):p[2 * i + 1], 0:]
            # 单槽分离及其板极短路检测
            for j in range(num2[1] - num2[0] + 1):
                im1bar = imBars[(q[i][j][1] - 1):q[i][j][3], (q[i][j][0] - 1):q[i][j][2]]
                # im1bar = np.resize(im1bar,[num3*10,100])
                # plt.imshow(im1bar,cmap='gray',interpolation='bicubic')
                # plt.show()
                diagBars = self.stdDetect(im1bar.T, minT, maxT, num3)  # 输入图片中板极纵向排列，0:正常 1:轻度 2:中度 3:重度
                key = str(i + 1) + '-' + str(j + 1)
                diag[key] = diagBars
                #
                # plt.figure()
                # plt.subplot(2, 1, 1)
                # plt.imshow(im1bar.T, cmap='gray', interpolation='bicubic')
                # plt.subplot(2, 1, 2)
                # plt.axis([1, num3, 0, 3])
                # plt.plot(list(range(1, num3 + 1)), diagBars, marker='*')
                # plt.savefig('SDC_' + str(i + 1) + '-' + str(j + 1) + '.jpg', dpi=120)
                # plt.show()

        return diag

    def MyCheck(self, path, maxT, minT):
        '''
        filePath = 'E:\\MatlabCode\\ElecBarCrop_20210707\\JiangXi\\Images\\'
        imList = os.listdir(filePath)
    #    print(imList)
        k=0
        #l=len(imList)
        #imPath = 'E:\\MatlabCode\\ElecBarCrop_20210707\\JiangXi\\ImTest.jpg'
        imPath = filePath+imList[k]
        '''

        # 'E:\\PythonProject\\SCD\\Images\\capture20210716_082701.jpg'
        imPath = path  # 'E:\\PythonProject\\ShortCircuitDetection\\Test003.jpg'
        num1 = [1, 2]  # 起始-结束整槽号
        num2 = [1, 12]  # 起始-结束单槽号
        num3 = 38  # number of plates in one electrobath
        # print(imPath)
        img = Image.open(imPath)  # read the image ( PIL image )
        diag = self.ShortCircuitDetect(img, minT, maxT, num3, num2, num1)  # 短路检测
        return diag

